﻿import flash.filters.BevelFilter;
import flash.filters.DropShadowFilter;

import com.yourdomain.spreadshop.gui.GUI;

import net.spreadshirt.logger.Logger;

/**
 * The Module class provides the main movie clips with some methods
 * to show and hide the clip or set it the front.
 * 
 * It also attaches the drag 'n drop behavior and some graphic effects.
 */
class com.yourdomain.spreadshop.gui.mod.lib.Module {

	// The movie clip.
	public var clip:MovieClip;

	// The reference to the GUI class.
	private var _gui:GUI;

	// The distance to the stages border.
	private static var _BORDER:Number = 8;

	// Some global settings.
	public static var FILTER_GLOBAL_ANGLE:Number = 90;

	public static var FILTER_MAIN_SHADOW:DropShadowFilter =
	new DropShadowFilter(
    	1, // [distance:Number]
    	FILTER_GLOBAL_ANGLE, // [angle:Number]
    	0x000000, // [color:Number]
    	.2, // [alpha:Number]
    	8, // [blurX:Number]
    	8, // [blurY:Number]
    	1, // [strength:Number]
    	1, // [quality:Number]
    	false, // [inner:Boolean]
    	false, // [knockout:Boolean]
    	false // [hideObject:Boolean]
    );

 	public static var FILTER_MAIN_BEVEL:BevelFilter =
 	new BevelFilter(
		1, // [distance:Number]
		FILTER_GLOBAL_ANGLE, // [angle:Number]
		0xffffff, // [highlightColor:Number]
		1, // [highlightAlpha:Number]
		0x000000, // [shadowColor:Number]
		.5, // [shadowAlpha:Number]
		2, // [blurX:Number]
		2, // [blurY:Number]
		1, // [strength:Number] 0.. 255 (1)
		1, // [quality:Number] 1, 2, 3
		"inner", // [type:String]
		false // [knockout:Boolean]
	);

	public static var FILTER_SUB_SHADOW:DropShadowFilter =
	new DropShadowFilter(
    	1, // [distance:Number]
    	FILTER_GLOBAL_ANGLE, // [angle:Number]
    	0x000000, // [color:Number]
    	.1, // [alpha:Number]
    	4, // [blurX:Number]
    	4, // [blurY:Number]
    	1, // [strength:Number]
    	1, // [quality:Number]
    	false, // [inner:Boolean]
    	false, // [knockout:Boolean]
    	false // [hideObject:Boolean]
    );

	/**
	 * Module Constructor
	 */
	public function Module(
		gui:GUI,
		module:MovieClip,
		visibility:Boolean,
		title:String,
		xpos:Number,
		ypos:Number
	) {
		_gui = gui;
		clip = module;
		// Set position of the module.
		clip._x = xpos;
		clip._y = ypos;
		// Setup the title textfield.
		clip.ground.title.tf.text = title;
		// Show or hide module.
		clip._visible = visibility;
		// Enables caching.
		clip.cacheAsBitmap = true;
		// Initialize the module.
		setup();
		// Support stage listener broadcasting (catches the onResize event)
		_gui.addListener(this);
	}

	/**
	 * Setup Modul behavior.
	 */
	private function setup():Void {
		// Attachs show and hide function to the movie clip.
		clip.show = getShow();
		clip.hide = getHide();
		// Attachs the focusOnRollOver check.
		clip.isOver = getIsOver();
		// Attachs the setToFront function to the movie clip.
		clip.setToFront = getSetToFront();
		// Set to front on mouse down.
		clip.onMouseDown = function():Void {
			if(this.isOver()) {
				this.setToFront();
			}
		};
		// Create blind button.
		clip.ground.useHandCursor = false;
		clip.ground.tabEnabled = false;
		clip.ground.onRelease = null;
		// The dragging behavior.
		clip.btdrag.useHandCursor = false;
		clip.btdrag.tabEnabled = false;
		clip.btdrag.gui = _gui;
		clip.btdrag.dxy = _BORDER;
		clip.btdrag.onPress = function():Void {
			this._parent.setToFront();
			this._parent.startDrag(
				false,
				this.dxy,
				this.dxy,
				Stage.width - this._parent.ground._width - this.dxy,
				Stage.height - this._parent.ground._height - this.dxy
			);
			this._parent.ground._alpha = 50;
			this.gui.startDragging();
		};
		clip.btdrag.onReleaseOutside =
		clip.btdrag.onRelease = function():Void {
			this._parent.stopDrag();
			this._parent.ground._alpha = 100;
			this.gui.stopDragging();
		};
		// Setup the close button.
		clip.btclose.tabEnabled = false;
		clip.btclose.onPress = function():Void {
			this._parent.hide();
		};
		// Setup the filter effects.
	    var filArray:Array = new Array();
	    filArray.push(FILTER_MAIN_SHADOW);
	    filArray.push(FILTER_MAIN_BEVEL);
	    clip.ground.filters = filArray;
	    clip.ground.cacheAsBitmap = true;
	    // Check the moduls position.
	    checkPosition();
	}

	/**
	 * Swap module to the front.
	 */
	private static function getSetToFront():Function {
		var fnc:Function = function():Void {
			var clip:MovieClip = this._parent;
			var depth:Number = clip._parent.getNextHighestDepth();
			clip.swapDepths(depth);
			// Show movie clip.
			this._visible = true;
			// Enforce redrawing.
			if(this.onEnterFrame == undefined) {
				this.onEnterFrame = function():Void {
					if(++this._alpha > 101) {
						this._alpha = 100;
						delete this.onEnterFrame;
					}
				};
			}
		};
		return fnc;
	}

	/**
	 * Show module.
	 */
	private static function getShow():Function {
		var fnc:Function = function():Void {
			var clip:MovieClip = this;
			clip.setToFront();
			clip._visible = true;
		};
		return fnc;
	}

	/**
	 * Hide module.
	 */
	private static function getHide():Function {
		var fnc:Function = function():Void {
			var clip:MovieClip = this;
			clip._visible = false;
		};
		return fnc;
	}

	/**
	 * Checks if the mouse cursor is in touch with the module.
	 */
	private static function getIsOver():Function {
		var fnc:Function = function():Boolean {
			var mc_con:MovieClip = this._parent._parent;
			var pos:Object = {
				x: mc_con._xmouse,
				y: mc_con._ymouse
			};
			var mods:Array = new Array();
			for(var i:String in mc_con) {
				if(typeof mc_con[i] == "movieclip") {
					var clip:MovieClip = mc_con[i];
					var isHit:Boolean = clip.hitTest(pos.x, pos.y, true);
					var isVisible:Boolean = clip[clip._name]._visible;
					var level:Number = clip.getDepth();
					if(isHit && isVisible) {
						mods.push({
							clip: clip[clip._name],
							level: level
						});
					}
				}
			}
			mods.sortOn("level", Array.DESCENDING | Array.NUMERIC);
			var isInTouch:Boolean = (mods[0].clip == this);
			return isInTouch;
		};
		return fnc;
	}

	/**
	 * Checks positions when the stage is resized.
	 */
	private function checkPosition():Void {
		var w:Number = clip.ground._width;
		var h:Number = clip.ground._height;
		if(clip._x + w > Stage.width - _BORDER) {
			var x:Number = Stage.width - w - _BORDER;
			clip._x = (x > _BORDER) ? x : _BORDER;
		}
		if(clip._y + h > Stage.height - _BORDER) {
			var y:Number = Stage.height - h - _BORDER;
			clip._y = (y > _BORDER) ? y : _BORDER;
		}
	}

}
